# 加载库
import paddle.fluid as fluid
import numpy as np
import os
import paddle


use_cuda = True
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()

# 定义数据
train_data = np.array([[1.0], [2.0], [3.0], [4.0]]).astype('float32')
y_true = np.array([[2.0], [4.0], [6.0], [8.0]]).astype('float32')
# 定义网络
x = fluid.layers.data(name='x', shape=[1], dtype='float32')
y = fluid.layers.data(name='y', shape=[1], dtype='float32')
y_predict = fluid.layers.fc(input=x, size=1, act=None)
# 定义损失函数
cost = fluid.layers.square_error_cost(input=y_predict, label=y)
avg_cost = fluid.layers.mean(cost)
# 定义优化方法
sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.01)
sgd_optimizer.minimize(avg_cost)
# 参数初始化
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
# 开始训练，迭代100次
for i in range(3000):
    out = exe.run(feed={'x': train_data, 'y': y_true},
                  fetch_list=[y_predict.name, avg_cost.name])

# 保存模型
# 如果保存路径不存在就创建
model_save_dir = r".\model"
if not os.path.exists(model_save_dir):
    os.makedirs(model_save_dir)

# 保存训练参数到指定路径中，构建一个专门用预测的program
fluid.io.save_inference_model(model_save_dir,  # 保存推理model的路径
                              ['x'],  # 推理（inference）需要 feed 的数据
                              [y_predict],  # 保存推理（inference）结果的 Variables
                              exe)  # exe 保存 inference model


infer_exe = fluid.Executor(place)  # 创建推测用的executor
inference_scope = fluid.core.Scope()  # Scope指定作用域

with fluid.scope_guard(inference_scope):  # 修改全局/默认作用域（scope）, 运行时中的所有变量都将分配给新的scope。
    # 从指定目录中加载 推理model(inference model)
    [inference_program,  # 推理的program
     feed_target_names,  # 需要在推理program中提供数据的变量名称
     fetch_targets] = fluid.io.load_inference_model(  # fetch_targets: 推断结果
        model_save_dir,  # model_save_dir:模型训练路径
        infer_exe)  # infer_exe: 预测用executor
    # 获取预测数据
    # 观察结果
    test_data = np.array([[8.0, 16.0], [7.0, 14.0], [6.0, 12.0], [200.0, 400.0]]).astype('float32')

    test_x = np.array([data[0] for data in test_data]).astype("float32").reshape((4, 1))
    test_y = np.array([data[1] for data in test_data]).astype("float32")
    results = infer_exe.run(inference_program,  # 预测模型
                            feed={feed_target_names[0]: np.array(test_x)},  # 喂入要预测的x值
                            fetch_list=fetch_targets)  # 得到推测结果

    print("infer results: (House Price)")
    for idx, val in enumerate(results[0]):
        print("%d: %.2f" % (idx, val))
    print("ground truth:")
    for idx, val in enumerate(test_y):
        print("%d: %.2f" % (idx, val))
